#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>

/**
 *开发板/dev/ttyS4 回环测试
 *
 */ 

static int uart_open(char *pdev, int baud_rate)
{
    int i;
    speed_t speed = 0;
    static struct termios ttyset;
    int fd;

    /* 
     * first open with non-blocking mode: we need
     * 1) if GPS chip is started just now, we must wait until it gets ready.
     * 2) else sweep possible UBX garbage 
     */
    fd = open(pdev, O_RDWR | O_NOCTTY);
    if (fd < 0) {
        printf("open device %s failed: %s\n", pdev, strerror(errno));
        return -1;
    }

    printf("open uart-dev: %s, baud-rate: %d, fd: %d\n", pdev, baud_rate, fd);

    /* Save original terminal parameters */
    if (tcgetattr(fd, &ttyset) != 0) {
        printf("get device attribute failed: %s\n", pdev);
        return -2;
    }

    switch (baud_rate) {
        case 4800:
            speed = B4800;
            break;
        case 9600:
            speed = B9600;
            break;
        case 19200:
            speed = B19200;
            break;
        case 38400:
            speed = B38400;
            break;
        case 115200:
            speed = B115200;
            break;
        default:
            break;
    }

    if (speed == 0) {
        printf("bad port baud rate: %d\n", baud_rate);
        return -3;
    }

    ttyset.c_iflag = ttyset.c_oflag = ttyset.c_lflag = 0;
    ttyset.c_cflag = CS8 | CLOCAL | CREAD;
    ttyset.c_lflag &= ~(ICANON | ISIG | ECHO);

    for (i = 0; i < NCCS; i++) {
        ttyset.c_cc[i] = -1;
    }

    ttyset.c_cc[VMIN] = 0;

    /*
     * unit: 1/10 second, max: 30
     * NOTE: this also means message send rate must <= 3 seconds.
     */
    ttyset.c_cc[VTIME] = 30;

    if (tcsetattr(fd, TCSANOW, &ttyset) != 0) {
        printf("Unable to set UART attribute: %s\n", strerror(errno));
        return -4;
    }

    cfsetispeed(&ttyset, speed); 
    cfsetospeed(&ttyset, speed);
    tcsetattr(fd, TCSANOW, &ttyset);

    return fd;
}

int uart_test(int argc, char *argv[])
{
    int rv;
    int baud = 115200;  //波特率设置
    char wdata[6] = {0x11, 0x22, 0x33, 0x44, 0x55, 0x66}; //往串口写6个字节,从串口4发送出去
    char rdata[6]; //从串口4接收6个字节
    int len = sizeof(wdata) / sizeof(wdata[0]);
    int i;
    char *pdev = "/dev/ttyS4"; //确定串口4的设备文件
    int fd;

    if (argc > 1) {
        if (strstr(argv[1], "-h")) {
            printf("%s -d <dev:/dev/ttyS4> -b <baud:115200>\n", argv[0]);
            return 0;
        }

        if (argc > 2) {
            if (strstr(argv[1], "-b")) {
                baud = atoi(argv[2]);
            } else if (strstr(argv[1], "-d")) {
                pdev = argv[2];
            }
            if (argc > 4) {
                if (strstr(argv[3], "-b")) {
                    baud = atoi(argv[4]);
                } else if (strstr(argv[3], "-d")) {
                    pdev = argv[4];
                }
            }
        }
    }

    /* 打开串口设备并设置相关属性 */
    fd = uart_open(pdev, baud);
    if (fd < 0) {
        return fd;
    }

    /* 向串口设备写入固定数据 */
    rv = write(fd, wdata, len);
    printf("send %d bytes: ", rv);
    for (i = 0; i < rv; i++) {
        printf("%02x ", wdata[i]);
    }
    printf("\n");

    /* 从串口设备读取数据 */
    rv = read(fd, rdata, len);
    printf("recv %d bytes: ", rv);
    for (i = 0; i < rv; i++) {
        printf("%02x ", wdata[i]);
    }
    printf("\n");
    
    /* 关闭串口设备描述符 */
    close(fd);

    return 0;
}

int main(int argc, char *argv[])
{
    int rv;

    printf("uart-test begin...\n");
    rv = uart_test(argc, argv);
    printf("uart-test end.\n");

    exit(rv);
}

